/**
* @brief 统一驱动: GPIO 驱动的开关
 * @author 张勇 41204@qq.com
 * @date 2022-04
*/

#include "button.h"

/// @brief 按钮状态轮询处理循环
static void checkButtonStateTask(size_t cookie_size, void* cookie) {
	unidrv_button_t *dev = (unidrv_button_t*)mcu_get_pointer(cookie);
	if(!dev || !dev->callback) { return; }
	
    // 获取按键状态
    unidrv_button_state_t newState = unidrv_button_state(dev);

    // case1: 无按键按下，不管
    if((newState == UNIDRV_BUTTON_UP) && (dev->lastState == UNIDRV_BUTTON_UP)) {
        dev->keyDownTime = 0;
		
		// 计算点击间隔
		uint32_t clickInterval = dev->lastClickTime ? unios_ms_elapsed(dev->lastClickTime) : UNIDRV_BUTTON_CLICKS_INTERVAL;
		// 根据间隔时间来判断连击是否结束，触发相应click事件
		if(dev->clickTimes && clickInterval >= UNIDRV_BUTTON_CLICKS_INTERVAL) {
			if(dev->clickTimes >= 3) {
				dev->callback(dev->callback_cookie, dev, UNIDRV_BUTTON_EVENT_CLICK3);
			} else if(dev->clickTimes >= 2) {
				dev->callback(dev->callback_cookie, dev, UNIDRV_BUTTON_EVENT_CLICK2);
			} else if(dev->clickTimes >= 1) {
				dev->callback(dev->callback_cookie, dev, UNIDRV_BUTTON_EVENT_CLICK);
			}
			// 连击状态复位
			dev->lastClickTime = 0;
			dev->clickTimes = 0;
		}
		
        return;
    }

    // case2: 按键刚按下，记住按下时间
    if((newState == UNIDRV_BUTTON_DOWN) && (dev->lastState == UNIDRV_BUTTON_UP)) {
        dev->lastState = UNIDRV_BUTTON_DOWN;
        dev->keyDownTime = unios_ms_now();
		dev->onDownTriggered = false;
		dev->onLongPress1Triggered = false;
		dev->onLongPress2Triggered = false;
        return;
    }

    // 计算按下了多长时间
    uint32_t keepTime = unios_ms_elapsed(dev->keyDownTime);

    // case3: 按键松开
    if((newState == UNIDRV_BUTTON_UP) && (dev->lastState == UNIDRV_BUTTON_DOWN)) {
        dev->lastState = UNIDRV_BUTTON_UP;

        if(keepTime < UNIDRV_BUTTON_JITTER_TIME) {
            // 按键抖动，不管
            return;
        } else if(keepTime < 3*UNIDRV_BUTTON_CLICKS_INTERVAL) {
			// 点击事件
			dev->clickTimes++;
			dev->lastClickTime = unios_ms_now();
        }

        // 触发 Up 事件
		dev->callback(dev->callback_cookie, dev, UNIDRV_BUTTON_EVENT_UP);
        return;
    }

    // case4: 按键持续按下
    if((newState == UNIDRV_BUTTON_DOWN) && (dev->lastState == UNIDRV_BUTTON_DOWN)) {
        if(keepTime >= UNIDRV_BUTTON_LONGPRESS_TIME2) {
            // 触发 LongPress2 事件
			if(!dev->onLongPress2Triggered) dev->callback(dev->callback_cookie, dev, UNIDRV_BUTTON_EVENT_LONG_PRESS2);
			dev->onLongPress2Triggered = true;
        } else if(keepTime >= UNIDRV_BUTTON_LONGPRESS_TIME1) {
            // 触发 LongPress1 事件
			if(!dev->onLongPress1Triggered) dev->callback(dev->callback_cookie, dev, UNIDRV_BUTTON_EVENT_LONG_PRESS1);
			dev->onLongPress1Triggered = true;
        } else if(keepTime >= UNIDRV_BUTTON_JITTER_TIME) {
            // 触发 Down 事件
			if(!dev->onDownTriggered) dev->callback(dev->callback_cookie, dev, UNIDRV_BUTTON_EVENT_DOWN);
			dev->onDownTriggered = true;
        }
        return;
    }
}

void unidrv_button_listen(unidrv_button_t* dev, bool enable) {
	// 如果没有 funcIsDown，则不可使能
	if(!dev || !dev->funcIsDown) { return; }
	
	if(enable) {
		// 进入监听状态前初始化状态
		dev->lastState = UNIDRV_BUTTON_UP;
		dev->keyDownTime = 0;
		dev->lastClickTime = 0;
		dev->clickTimes = 0;
		dev->onDownTriggered = false;
		dev->onLongPress1Triggered = false;
		dev->onLongPress2Triggered = false;
		// 创建轮询任务
		if(!dev->pollTaskId) dev->pollTaskId = unios_task_run_routine(checkButtonStateTask, sizeof(void*), &dev);
	} else {
		// 如果之前已经创建了轮询任务，但要停止监听，就必须停止任务
		if(dev->pollTaskId) unios_task_destroy(&dev->pollTaskId);
	}
}
